﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using JsonFx.Json;
using SystemDebug = System.Diagnostics.Debug;

using UnityEngine;
using Object = UnityEngine.Object;

public class GameData
{
	private static GameData instance;

	public DStartChar[] startChar;
	[Obsolete]
	public DBaseCharacter[] raceData_Old = new DBaseCharacter[] { };
	[Obsolete]
	public DBaseCharacter[] classData_Old = new DBaseCharacter[] { };
	public DBaseCharacter_New[] raceData;
	public DBaseCharacter_New[] classData;
	public DCharacter[] character;
	public DLegion[] legion;
	public DRegion[] region;
	public DRegionLevel[] regionLevel;
	public DRegionSpot[] regionSpot;
	public DTrait[] trait;
	public DRegionCharTrait[] regionCharTrait;
	public DPve[] pve;
	public DDispatch[] dispatch;
	public DDispatchReward[] dispatchReward;
	public DExtendWar[] extendWar;
	public DConstNumber[] constNumber;
	public DCharModel[] charModel;
	public DCharName[] charName;
	public DNameList[] nameList;
	public DInvadeReward[] invadeReward;
	public DSkills[] skills;
	public DItem[] item;
	public DItemUpgrade[] itemUpgrade;
    public DPartySync[] partySync;
    public DItemModelDefine[] itemModelDefine;
    public DModelDefine[] modelDefine;
	[Obsolete]
	public DBossData[] bossData_Old = new DBossData[] { };
	public DBoss_New[] bossData;
	public DBossCharTrait[] bossCharTrait;
	public DBossReward[] bossReward;
	public DNpcData[] npcData;
	public DRegionBattle[] regionBattle;
    public DStore[] store;
    public DStoreCharacter[] storeCharacter;
    public DRandomTraitList[] randomTraitList;
    public DQuestInfo[] quest;
    public DAchievementInfo[] achieve;
    public DGStarBossList[] gstarBossList;

	public static GameData Inst { get { Init(); return instance; } }
	
	public static void Init()
	{
		if (instance == null)
		{
            string data = null;
            using (System.IO.StreamReader r = System.IO.File.OpenText(Application.persistentDataPath + "/data.json"))
            {
                data = r.ReadToEnd();
            }
            instance = JsonReader.Deserialize<GameData>(data);
			Debug.Log("gamedata init");			
		}
	}

	
	public DStartChar GetStartChar(int id)
	{
		return startChar.First(d => d.ID == id);
	}

	[Obsolete]
	public DBaseCharacter GetClassData_Old(int id)
	{
		for(int i=0; i< classData_Old.Length; i++)
		{
			if( classData_Old[i].ID == id)
				return classData_Old[i];
		}
		return null;
	}

	[Obsolete]
	public DBaseCharacter GetRaceData_Old(int id)
	{
		for(int i=0; i< raceData_Old.Length; i++)
		{
			if( raceData_Old[i].ID == id)
				return raceData_Old[i];
		}
		return null;
	}

	public DBaseCharacter_New GetClassData(int id)      // 새로운 클래스 데이터 DClass에서 아이디값 검출
	{
		for (int i = 0; i < classData.Length; i++)
		{
			if (classData[i].ID == id)
				return classData[i];
		}
		return null;
	}

	public DBaseCharacter_New GetRaceData(int id)      // 새로운 클래스 데이터 DClass에서 아이디값 검출
	{
		for (int i = 0; i < raceData.Length; i++)
		{
			if (raceData[i].ID == id)
				return raceData[i];
		}
		return null;
	}

	public DTrait GetTrait(int id)
	{
		for(int i=0; i< trait.Length; i++)
		{
			if( trait[i].id == id)
				return trait[i];
		}
		return null;
	}

	public DSkills GetSkill(int id)
	{
		for(int i=0; i< skills.Length; i++)
		{
			if(id == skills[i].traitID)
				return skills[i];
		}
		return null;
	}

	public int GetSkillPrior(int id)
	{
		for(int i=0; i< skills.Length; i++)
		{
			if(id == skills[i].traitID)
				return i;
		}
		return 9999;
	}

	public DConstNumber GetConstantData(string type)
	{
		return constNumber.First(d => d.name.Equals(type));
	}

	public int GetMaxResourceSpotCount(int regionId)
	{
		int count = 0;
		foreach(DRegionSpot spotInfo in regionSpot)
		{
			if( spotInfo.regionID == regionId )
				count++;
		}

		return count;
	}

    public DPartySync GetPartySync(int id)
    {
        for (int i = 0; i < skills.Length; i++)
        {
            if (id == partySync[i].syncID)
                return partySync[i];
        }
        return null;
    }

    [NonSerialized]
    Dictionary<int, string> modelDic;
    public Dictionary<int, string> ModelDefineDic
    {
        get
        {
            if(modelDic == null)
            {
                modelDic = new Dictionary<int, string>();

                foreach (DModelDefine t in GameData.Inst.modelDefine)
                {
                    modelDic.Add(t.modelNo, t.modelName);
                }
            }
            return modelDic;
        }
    }

	public int GetModelIDFromName(string _modelName)
	{
		foreach (DModelDefine t in GameData.Inst.modelDefine)
		{
			if(t.modelName== _modelName)
				return t.modelNo;
		}
		return 0;
	}

    [NonSerialized]
    Dictionary<int, string> itemDic;
    public Dictionary<int, string> ItemDefineDic
    {
        get
        {
            if (itemDic == null)
            {
                itemDic = new Dictionary<int, string>();

                foreach (DItemModelDefine t in itemModelDefine)
                {
                    itemDic.Add(t.itemModelNo, t.itemModelName);
                }
            }
            return itemDic;
        }
    }

	public int GetItemRarity(int itemId)
	{
		foreach(DItem info in item)
		{
			if( info.itemID == itemId )
				return info.rarity;
		}

		return 0;
	}

//#if CACHE_PREFAB
//	// Prefab Chache (temporary implemented by forour)
//	[NonSerialized]
//	private readonly Dictionary<int, Entity> _cached_prefabs = new Dictionary<int, Entity>();
//
//
//	public Entity InstantiateCharacterEntity( int model_id )
//	{
//		// cached된  prefab 찾기
//		Entity prefab;
//		if( _cached_prefabs.TryGetValue( model_id, out prefab ) )
//		{
//			if( !prefab )
//				Debug.LogError( "Entity Cache Error - entity was GCed. : " + ModelDefineDic[model_id] );
//		}
//		// prefab 로드
//		else
//		{
//			string model_name = ModelDefineDic[model_id];
//			prefab = (Entity)ResourcesManager.Load( "Prefab/Battle/Character/" + model_name );
//			_cached_prefabs[model_id] = prefab;
//			prefab.name = model_name;
//			//prefab.transform.parent = Main.CacheEntity.transform;
//		}
//
//		// instanciate entity
//		return (Entity)Object.Instantiate( prefab );
//	}
//#endif


	public DNpcData GetNPCData( int npcID )
	{
		foreach(DNpcData ndata in npcData) {
			if(npcID == ndata.npcID)
				return ndata;
		}
		return null;
	}

	[Obsolete]
	public DBossData GetBossData_Old(int bossID)
	{
		foreach(DBossData ndata in bossData_Old) {
			if(bossID == ndata.bossID)
				return ndata;
		}
		return null;
	}

	public IEnumerable<DBoss_New> GetBossData(int bossID)
	{
		//foreach (DBoss_New ndata in bossData)
		//{
		//	if (bossID == ndata.bossID)
		//		return ndata;
		//}
		//return null;
		return bossData.Where(data => data.bossID == bossID);
	}

	public DRegion GetRegionData( int regionId )
	{
		foreach(DRegion regionInfo in region)
		{
			if(regionInfo.regionId == regionId)
			{
				return regionInfo;
			}
		}
		return null;
	}
	
    public DAchievementInfo GetAchievementInfo(int id)
    {
        foreach(DAchievementInfo info in achieve)
        {
            if (info.achieveID == id)
                return info;
        }

        return null;
    }
    
    public DStore GetStoreGoodInfo(int goodId)
    {
        foreach(DStore storeInfo in GameData.Inst.store)
        {
            if( goodId == storeInfo.goods )
            {
                return storeInfo;
            }
        }

        return null;
    }

	public DStoreCharacter[] GetCharDrawItemListByGrade(DrawItemGrade drawGrade)
	{
		List<DStore> tempList = new List<DStore>();
		foreach(DStore storeInfo in GameData.Inst.store)
		{
			if( storeInfo.category == 1 )
			{
				if( storeInfo.tab == (int)drawGrade )
				{
					tempList.Add(storeInfo);
				}
			}
		}

		tempList.Sort( (c, d) => c.order.CompareTo(d.order) );

		DStoreCharacter[] charInfoList = new DStoreCharacter[tempList.Count];

		for(int i=0; i<tempList.Count; i++)
		{
			foreach(DStoreCharacter charInfo in storeCharacter)
			{
				if( charInfo.charID == tempList[i].goods )
				{
					charInfoList[i] = charInfo;
					break;
				}
			}
		}

		return charInfoList;
	}

	public DStoreCharacter GetCharDrawItemInfo(int itemId)
	{
		foreach(DStoreCharacter charInfo in storeCharacter)
		{
			if( itemId == charInfo.charID )
				return charInfo;
		}

		return null;
	}

	public int[] GetRandomTraitList(int listId)
	{
		List<int> tempList = new List<int>();
		foreach(DRandomTraitList randomTraitInfo in randomTraitList)
		{
			if( randomTraitInfo.listID == listId )
				tempList.Add(randomTraitInfo.traitID);
		}

		return tempList.ToArray();
	}

	public bool IsExistInRandomTraitList(int listId, int traitId)
	{
		List<int> tempList = new List<int>();
		foreach(DRandomTraitList randomTraitInfo in randomTraitList)
		{
			if( randomTraitInfo.listID == listId && randomTraitInfo.traitID == traitId )
				return true;
		}
		
		return false;
	}

	public DQuestInfo GetQuestInfo(int questId)
	{
		foreach(DQuestInfo info in quest)
		{
			if( info.questID == questId )
				return info;
		}

		return null;
	}

	public bool CanStartQuest
	{
		get 
		{
			foreach(DQuestInfo questInfo in quest)
			{
				if( questInfo.questID == UserData.Instance.userModel.questInfo.questId )
				{
					if( questInfo.legionLv <= UserData.Instance.userModel.level )
						return true;
					else
						return false;
				}
			}

			return false;
		}
	}

    public DGStarBossList GetGStarBossListByRegionId(int regionId)
    {
        foreach(DGStarBossList item in gstarBossList)
        {
            if(item.regionID == regionId)
            {
                return item;
            }
        }

        return null;
    }
}

[Obsolete]
public class DBossData
{
	public int bossID;
	public short modelID;
	public short lv;
	public short maxLv;
	public int HP;
	public short hpMod;
	public short armor;
	public short armorMod;
	public short res;
	public short resMod;
	public short init;
	public short initMod;
	public short atkType;
	public short atkRating;
	public short aRMod;
	public short rateOfAtk;
	public short skillProb;
	public short sPMod;
	public short taunt;
	public short unisonAtk;
	public short unisonDef;
	public short trait1;
	public short trait2;
	public short trait3;
	public short trait4;
	public short trait5;
}

public class DBossCharTrait
{
	public short charRewardId;
	public short traitId;
	public short weight;	
}

public class DBossReward
{
	public int bossId;
	public short regionId;
	public short bosslevelMin;
	public short bosslevelMax;
	public short legionExp;
	public short charExp;
	public int findKina;
	public short joinCharRewardId;
	public short value1;
	public short suppressCharRewardId;
	public short value2;
	public int joinString;
	public int suppressString;	
}

public class DRegionBattle {
	public short regionID;
	public short npcID;
	public short weight;
}

public class DNpcData {
	public int npcID;
	public short modelID;
	public short lv;
	public int HP;
	public short armor;
	public short res;
	public short init;
	public short atkType;
	public short atkRating;
	public short skillProb;
	public short taunt;
	public short unisonAtk;
	public short unisonDef;
	public short trait1;
	public short trait2;
	public short trait3;
	public short trait4;
	public short trait5;
}

public class DStartChar
{
	public short ID;
	public string name; // 이름
	public short charModel; // 모델
	public short race; // 종족
	public short trait1; // 특성
	public short trait2; // 특성
	public short trait3; // 특성
	public short trait4; // 특성
}

[Obsolete]
public class DBaseCharacter
{
	public short ID;				// id
	public short atkType;			// 공격타입 
	public short taunt;				// 어그로 
	public short baseHP;			// 기본생명력 
	public short baseAtk;			// 기본공격력 
	public short baseDef;			// 기본방어도 
	public short baseRes;			// 기본저항 
	public short growHP;			// HP보정치 
	public short growAtk;			// 공격력보정치 
	public short growDef;			// 방어도보정치 
	public short GrowRes;			// 저항보정치 
}

/// <summary>
/// dataDic 내부 값을 직접 변경할 경우 타입이 유지되는지 확인할 것.
/// </summary>
public class DBaseStat : IEnumerable<KeyValuePair<AptitudeID_New, ValueType>>
{
	protected IDictionary<AptitudeID_New, ValueType> dataDic = new Dictionary<AptitudeID_New, ValueType>();	// 순차 접근

	public ValueType this[AptitudeID_New index]
	{
		get
		{
			return dataDic[index];
		}

		set
		{
			if (dataDic[index] is short)
				dataDic[index] =  Convert.ToInt16(value);
			else if (dataDic[index] is float)
                dataDic[index] = (float)Convert.ToDouble(value);
		}
	}

	public short atkType { get { return (short)dataDic[AptitudeID_New.atkType]; } set { dataDic[AptitudeID_New.atkType] = value; } }
	public short baseAtk { get { return (short)dataDic[AptitudeID_New.baseAtk]; } set { dataDic[AptitudeID_New.baseAtk] = value; } }
	public short growAtk { get { return (short)dataDic[AptitudeID_New.growAtk]; } set { dataDic[AptitudeID_New.growAtk] = value; } }
	public short assist { get { return (short)dataDic[AptitudeID_New.assist]; } set { dataDic[AptitudeID_New.assist] = value; } }
	public short baseHP { get { return (short)dataDic[AptitudeID_New.baseHP]; } set { dataDic[AptitudeID_New.baseHP] = value; } }
	public short growHP { get { return (short)dataDic[AptitudeID_New.growHP]; } set { dataDic[AptitudeID_New.growHP] = value; } }
	public short baseDef { get { return (short)dataDic[AptitudeID_New.baseDef]; } set { dataDic[AptitudeID_New.baseDef] = value; } }
	public short growDef { get { return (short)dataDic[AptitudeID_New.growDef]; } set { dataDic[AptitudeID_New.growDef] = value; } }
	public short init { get { return (short)dataDic[AptitudeID_New.init]; } set { dataDic[AptitudeID_New.init] = value; } }
	public short taunt { get { return (short)dataDic[AptitudeID_New.taunt]; } set { dataDic[AptitudeID_New.taunt] = value; } }
	public short melee { get { return (short)dataDic[AptitudeID_New.melee]; } set { dataDic[AptitudeID_New.melee] = value; } }
	public short growMelee { get { return (short)dataDic[AptitudeID_New.growMelee]; } set { dataDic[AptitudeID_New.growMelee] = value; } }
	public short range { get { return (short)dataDic[AptitudeID_New.range]; } set { dataDic[AptitudeID_New.range] = value; } }
	public short growRange { get { return (short)dataDic[AptitudeID_New.growRange]; } set { dataDic[AptitudeID_New.growRange] = value; } }
	public short magic { get { return (short)dataDic[AptitudeID_New.magic]; } set { dataDic[AptitudeID_New.magic] = value; } }
	public short growMagic { get { return (short)dataDic[AptitudeID_New.growMagic]; } set { dataDic[AptitudeID_New.growMagic] = value; } }
	public short pulse { get { return (short)dataDic[AptitudeID_New.pulse]; } set { dataDic[AptitudeID_New.pulse] = value; } }
	public short growPulse { get { return (short)dataDic[AptitudeID_New.growPulse]; } set { dataDic[AptitudeID_New.growPulse] = value; } }
	public short special { get { return (short)dataDic[AptitudeID_New.special]; } set { dataDic[AptitudeID_New.special] = value; } }
	public short growSpecial { get { return (short)dataDic[AptitudeID_New.growSpecial]; } set { dataDic[AptitudeID_New.growSpecial] = value; } }
	public float evade { get { return (float)dataDic[AptitudeID_New.evade]; } set { dataDic[AptitudeID_New.evade] = value; } }
	public short evadeMod { get { return (short)dataDic[AptitudeID_New.evadeMod]; } set { dataDic[AptitudeID_New.evadeMod] = value; } }
	public float defDamage { get { return (float)dataDic[AptitudeID_New.defDamage]; } set { dataDic[AptitudeID_New.defDamage] = value; } }
	public short defDamageMod { get { return (short)dataDic[AptitudeID_New.defDamageMod]; } set { dataDic[AptitudeID_New.defDamageMod] = value; } }
	public short HPMod { get { return (short)dataDic[AptitudeID_New.HPMod]; } set { dataDic[AptitudeID_New.HPMod] = value; } }
	public short healRate { get { return (short)dataDic[AptitudeID_New.healRate]; } set { dataDic[AptitudeID_New.healRate] = value; } }
	public short res { get { return (short)dataDic[AptitudeID_New.res]; } set { dataDic[AptitudeID_New.res] = value; } }
	public short skillRate { get { return (short)dataDic[AptitudeID_New.skillRate]; } set { dataDic[AptitudeID_New.skillRate] = value; } }
	public short skillRateMod { get { return (short)dataDic[AptitudeID_New.skillRateMod]; } set { dataDic[AptitudeID_New.skillRateMod] = value; } }
	public short critRate { get { return (short)dataDic[AptitudeID_New.critRate]; } set { dataDic[AptitudeID_New.critRate] = value; } }
	public short critPower { get { return (short)dataDic[AptitudeID_New.critPower]; } set { dataDic[AptitudeID_New.critPower] = value; } }
	public short attackAssist { get { return (short)dataDic[AptitudeID_New.attackAssist]; } set { dataDic[AptitudeID_New.attackAssist] = value; } }
	public short defAssist { get { return (short)dataDic[AptitudeID_New.defAssist]; } set { dataDic[AptitudeID_New.defAssist] = value; } }
	public short atkInit { get { return (short)dataDic[AptitudeID_New.atkInit]; } set { dataDic[AptitudeID_New.atkInit] = value; } }
	public float atkCooltime { get { return (float)dataDic[AptitudeID_New.atkCooltime]; } set { dataDic[AptitudeID_New.atkCooltime] = value; } }
	public short atkCooltimeMod { get { return (short)dataDic[AptitudeID_New.atkCooltimeMod]; } set { dataDic[AptitudeID_New.atkCooltimeMod] = value; } }
	public short moveTime { get { return (short)dataDic[AptitudeID_New.moveTime]; } set { dataDic[AptitudeID_New.moveTime] = value; } }
	public short moveTimeMod { get { return (short)dataDic[AptitudeID_New.moveTimeMod]; } set { dataDic[AptitudeID_New.moveTimeMod] = value; } }
	public short getFromAtk { get { return (short)dataDic[AptitudeID_New.getFromAtk]; } set { dataDic[AptitudeID_New.getFromAtk] = value; } }
	public short getFromHit { get { return (short)dataDic[AptitudeID_New.getFromHit]; } set { dataDic[AptitudeID_New.getFromHit] = value; } }
	public short moveSpd { get { return (short)dataDic[AptitudeID_New.moveSpd]; } set { dataDic[AptitudeID_New.moveSpd] = value; } }
	public short moveSpdMod { get { return (short)dataDic[AptitudeID_New.moveSpdMod]; } set { dataDic[AptitudeID_New.moveSpdMod] = value; } }
	public float healPower { get { return (float)dataDic[AptitudeID_New.healPower]; } set { dataDic[AptitudeID_New.healPower] = value; } }
	public short healPowerMod { get { return (short)dataDic[AptitudeID_New.healPowerMod]; } set { dataDic[AptitudeID_New.healPowerMod] = value; } }

	IEnumerator IEnumerable.GetEnumerator()
	{
		return GetEnumerator();
	}

	public IEnumerator<KeyValuePair<AptitudeID_New, ValueType>> GetEnumerator()
	{
		return dataDic.GetEnumerator();
	}
}

/// <summary>
/// dataDic 내부 값을 직접 변경할 경우 타입이 유지되는지 확인할 것.
/// </summary>
public class DBaseCharacter_New : DBaseStat
{
	public int ID;
}

/// <summary>
/// dataDic 내부 값을 직접 변경할 경우 타입이 유지되는지 확인할 것.
/// </summary>
public class DBoss_New : DBaseStat
{
	public int bossID;
	public int modelID;
	public short phaseHP;
	public short phaseSet;
	public short[] enableAtkType;
	public short lv;
	public short bossTrait;
	public short atkRadius;
	public short maxLv;
	public short[] weakpoint;
}

public class DCharacter
{
	public short charLevel;			// 레벨 
	public int charExp;			// 경험치  
    public int charExpAcc;			// 누적 경험치  
}

public class DLegion
{
	public int legionLevel;
	public int legionExp;
	public int charNum;
	public int ratioPVE;
	public int ratioPVP;
	public int ratioDungeon;
}

public class DRegion
{
	public int regionId;
	public int order;
	public int maxCharLevel;
	public int dispatchTime;
}

public class DRegionLevel
{
	public int regionLevel;
	public int regionExp;
	public int dispatchNum;
	public int dispatchTime;
	public int charExp;
	public int legionExp;
	public int kina;
	public int levelupReward;
}

public class DRegionSpot
{
	public int id;
	public int regionID;
	public int spotID;
	public int bonusType;
	public int value1;
	public int value2;
}

public class DTrait
{
	public int id;
	public int effStat1;
	public int modStat1;
	public int effStat2;
	public int modStat2;
	public int effStat3;
	public int modStat3;
	public int traitType;
	public int[] exclusiveTrait; 
	public int weight;
}

public class DRegionCharTrait
{
	public int regionID;
	public int traitID;
	public int weight;
}

public class DPve
{
	public int pveID;
	public int regionID;
	public int meanLevel;
	public int npcListID;
	public int weight;
}

public class DDispatch
{
	public int charNum;
	public float timeMultiplier;
}

public class DDispatchReward
{
	public int regionID;
	public int rewardID;
	public int prob;
	public int type;
	public int value1;
	public int value2;
}

public class DExtendWar
{
	public int regionID;
	public int stage;
	public int npcListID;
	public int rewardType;
	public int value;
}

public class DConstNumber
{
	public string name;
	public int value;
}

public class DCharModel
{
	public int traitID;
    public int nameList;
	public int[] rarity1;
	public int[] rarity2;
	public int[] rarity3;
	public int[] rarity4;
	public int[] rarity5;
}

public class DCharName
{
	public int traitID;
	public int male;
	public int female;
}

public class DNameList
{
	public int listID;
	public int nameID;
}

public class DInvadeReward
{
	public int rewardID;
	public int rewardType;
	public int value1;
	public int value2;
}

public class DSkills
{
	public int traitID;
	public int skillType;
	public int targetNumber;
	public int targetType;
	public int rateType;
	public float rate;
	public float skillMod;
}

public class DItem
{
	public int itemID;
    public int modelID;
	public int itemType;
	public int part;
	public int[] itemClass;
	public int level;
	public int rarity;
	public int stackable;
	public int sell;
	public int price;
	public int upgradeMax;
	public int effectType1;
	public int effectValue1;
	public int effectValue1a;
	public float effectValue1b;
	public float effectValue1c;
	public int effectType2;
	public int effectValue2;
	public int effectValue2a;
	public float effectValue2b;
	public float effectValue2c;
}

public class DItemUpgrade
{
	public int rarity;
	public int upgradeLevel;
	public int cost;
	public int prob;
}

public class DModelDefine
{
    public int modelNo;
    public string modelName;
}

public class DItemModelDefine
{
    public int itemModelNo;
    public string itemModelName;
}

public class DPartySync
{
    public int syncID;
    public int pratyTrait1;
    public int pratyTrait2;
    public int pratyTrait3;
    public int pratyTrait4;
    public int targetAttribute;
    public int mod;

    //[NonSerialized]    
    public List<int> traits
    {
        get
        {
            List<int> list = new List<int> { pratyTrait1, pratyTrait2, pratyTrait3, pratyTrait4 };
            list.RemoveAll(is0);
            return list;
        }       
    }

    bool is0(int i)
    {
        return (i == 0);
    }
}

public class DStore
{
    public int category;
    public int tab;
    public int order;
    public int goods;
    public int payType;
    public int price;
    public int againPrice;
}

public class DStoreCharacter
{
    public int charID;
    public int nameID;
    public int modelNo;
    public int lv;
    public int trait1Type;
    public int trait1Value;
    public int trait2Type;
    public int trait2Value;
    public int trait3Type;
    public int trait3Value;
    public int trait4Type;
    public int trait4Value;
    public int trait5Type;
    public int trait5Value;
}

public class DRandomTraitList
{
    public int listID;
    public int traitID;
    public int weight;
}

public class DQuestInfo
{
    public int questID;
    public int nextID;
    public int legionLv;
    public int objective;
    public int value1;
    public int value2;
    public int reward1Type;
    public int reward1Value1;
    public int reward1Value2;
    public int reward2Type;
    public int reward2Value1;
    public int reward2Value2;
    public int reward3Type;
    public int reward3Value1;
    public int reward3Value2;
    public int reward4Type;
    public int reward4Value1;
    public int reward4Value2;
}

public class DAchievementInfo
{
    public int achieveID;
    public int objective;
    public int preCondition;
    public int value1;
    public int value2;
    public int value3;
    public int value4;
    public int[] multiValue;
    public int reward1Type;
    public int reward1Value1;
    public int reward1Value2;
    public int reward2Type;
    public int reward2Value1;
    public int reward2Value2;
    public int reward3Type;
    public int reward3Value1;
    public int reward3Value2;
    public int reward4Type;
    public int reward4Value1;
    public int reward4Value2;
}

public class DGStarBossList
{
    public int regionID;
    public int bossID;
    public int bossLv;
    public int legionExp;
    public int gold;
    public int[] charReward;
    public int[] itemReward;
}